package com.zeng.sim.support.server.socket;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zeng.sim.mapper.model.SimMsgCodeMappingEntity;
import com.zeng.sim.mapper.model.SimMsgRecordEntity;
import com.zeng.sim.service.SimMsgCodeMappingService;
import com.zeng.sim.service.SimMsgRecordService;
import com.zeng.sim.support.headStrategy.HeadStrategyFactory;
import com.zeng.sim.support.headStrategy.IHeadStrategy;
import com.zeng.sim.util.ApplicationContextUtil;
import com.zeng.sim.util.MsgUtil;
import com.zeng.sim.util.SimConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * 描述信息
 *
 * @author zengwanlin
 * @date 2023-12-25T13:53
 */
@Component
public class ServerSimBusiProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerSimBusiProcessor.class);

    @Autowired
    private SimMsgRecordService simMsgRecordService;

    /**
     * 业务处理
     * @param reqMsg 请求报文
     * @return left：响应报文编码名称，right：响应报文
     */
    public Pair<String, String> process(String reqMsg) {
        try {
            LOGGER.info("收到请求报文[{}]", reqMsg);

            IHeadStrategy reqHeadStrategy = HeadStrategyFactory.getReqHeadStrategy(reqMsg);
            LOGGER.info("获取到请求报文报文头策略类：" + reqHeadStrategy.getClass().getSimpleName());
            reqMsg = reqHeadStrategy.deleteHead(reqMsg);

            SimMsgRecordEntity respSimMsgRecordEntity = null;

            // 判断报文格式
            if (MsgUtil.isJson(reqMsg)) {
                // json报文
                LOGGER.info("当前报文为Json格式");
                String channelNo = MsgUtil.getChannelNoByJsonPath(reqMsg);
                String msgCode = MsgUtil.getMsgCodeByJsonPath(reqMsg);
                LOGGER.info("请求报文-渠道号[{}]，消息编码[{}]", channelNo, msgCode);

                respSimMsgRecordEntity = queryRespSimMsgRecord(channelNo, msgCode);
            }
            else if (MsgUtil.isXml(reqMsg)) {
                // xml报文
                LOGGER.info("当前报文为xml格式");
                String channelNo = MsgUtil.getChannelNoByXPath(reqMsg);
                String msgCode = MsgUtil.getMsgCodeByXPath(reqMsg);
                LOGGER.info("请求报文-渠道号[{}]，消息编码[{}]", channelNo, msgCode);

                respSimMsgRecordEntity = queryRespSimMsgRecord(channelNo, msgCode);
            }
            else {
                throw new IllegalArgumentException("未知的报文类型");
            }

            IHeadStrategy respHeadStrategy = HeadStrategyFactory
                .getHeadStrategy(respSimMsgRecordEntity.getHeadStrategy());
            String respMsg = respHeadStrategy.appendHead(respSimMsgRecordEntity.getMsgContent(),
                    respSimMsgRecordEntity.getCharsetName());
            LOGGER.info("返回响应报文名称[{}]，报文内容[{}]", respSimMsgRecordEntity.getMsgName(), respMsg);
            return new Pair<>(respSimMsgRecordEntity.getCharsetName(), respMsg);
        }
        catch (Exception e) {
            LOGGER.error("模拟服务端-业务处理出错，" + e.getMessage(), e);
            // 可在此处返回通用错误报文
            throw new IllegalStateException("模拟服务端-业务处理出错，" + e.getMessage(), e);
        }
    }

    /**
     * 业务处理
     * @param channelNo 渠道号（可能为空）
     * @param msgCode 报文编码
     * @return left：响应报文编码名称，right：响应报文
     */
    public Pair<String, String> process(String channelNo, String msgCode) {
        channelNo = StrUtil.emptyToDefault(channelNo, SimConstant.MSG_CHANNEL_NO_NONE);
        LOGGER.info("收到请求报文-渠道号[{}]，消息编码[{}]", channelNo, msgCode);
        SimMsgRecordEntity respSimMsgRecordEntity = queryRespSimMsgRecord(channelNo, msgCode);
        IHeadStrategy respHeadStrategy = HeadStrategyFactory.getHeadStrategy(respSimMsgRecordEntity.getHeadStrategy());
        String respMsg = respHeadStrategy.appendHead(respSimMsgRecordEntity.getMsgContent(),
                respSimMsgRecordEntity.getCharsetName());
        LOGGER.info("返回响应报文名称[{}]，报文内容[{}]", respSimMsgRecordEntity.getMsgName(), respMsg);
        return new Pair<>(respSimMsgRecordEntity.getCharsetName(), respMsg);
    }

    /**
     * 查询服务端报文
     * @param channelNo
     * @param msgCode
     * @return
     */
    public static SimMsgRecordEntity queryRespSimMsgRecord(String channelNo, String msgCode) {
        SimMsgCodeMappingService simMsgCodeMappingService = ApplicationContextUtil
            .getBean(SimMsgCodeMappingService.class);
        LambdaQueryWrapper<SimMsgCodeMappingEntity> mappingWrapper = new LambdaQueryWrapper<>();
        mappingWrapper.eq(SimMsgCodeMappingEntity::getReqChannelNo, channelNo);
        mappingWrapper.eq(SimMsgCodeMappingEntity::getReqMsgCode, msgCode);
        List<SimMsgCodeMappingEntity> msgCodeMappingEntityList = simMsgCodeMappingService.list(mappingWrapper);
        if (!CollectionUtils.isEmpty(msgCodeMappingEntityList)) {
            if (msgCodeMappingEntityList.size() != 1) {
                throw new IllegalArgumentException("报文映射关系重复，请求渠道号[" + channelNo + "]，请求报文编号[" + msgCode + "]");
            }
            SimMsgCodeMappingEntity msgCodeMappingEntity = msgCodeMappingEntityList.get(0);
            channelNo = msgCodeMappingEntity.getRespChannelNo();
            msgCode = msgCodeMappingEntity.getRespMsgCode();
            LOGGER.info("映射后的渠道号[{}]，报文编号[{}]", channelNo, msgCode);
        }

        SimMsgRecordService simMsgRecordService = ApplicationContextUtil.getBean(SimMsgRecordService.class);
        LambdaQueryWrapper<SimMsgRecordEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SimMsgRecordEntity::getBusiType, SimConstant.BUSI_TYPE_02);
        wrapper.eq(SimMsgRecordEntity::getChannelNo, channelNo);
        wrapper.eq(SimMsgRecordEntity::getMsgCode, msgCode);
        List<SimMsgRecordEntity> simMsgRecordEntityList = simMsgRecordService.list(wrapper);
        if (CollectionUtils.isEmpty(simMsgRecordEntityList)) {
            throw new IllegalArgumentException("服务端报文不存在，渠道号[" + channelNo + "]，报文编码[" + msgCode + "]");
        }
        if (simMsgRecordEntityList.size() != 1) {
            throw new IllegalArgumentException("服务端报文重复，渠道号[" + channelNo + "]，报文编码[" + msgCode + "]");
        }
        return simMsgRecordEntityList.get(0);
    }

}
